package com.organize.configure;

import com.autumn.mybatis.event.TableAutoDefinitionListener;
import com.autumn.zero.authorization.plugins.AuthorizationResourcesDataSourceListener;
import com.autumn.zero.authorization.plugins.ResourcesModulePlugin;
import com.organize.ComponentInfo;
import com.organize.application.callback.DefaultDictionaryTypeCallback;
import com.organize.application.callback.DictionaryTypeCallback;
import com.organize.application.services.DepartmentAppService;
import com.organize.application.services.EmployeeAppService;
import com.organize.application.services.impl.DepartmentAppServiceImpl;
import com.organize.application.services.impl.EmployeeAppServiceImpl;
import com.organize.context.OrganizeComponentMenuPluginCondition;
import com.organize.context.OsNotWindowsCondition;
import com.organize.context.OsWindowsCondition;
import com.organize.plugin.OrganizeResourcesModulePluginImpl;
import com.organize.rules.ComponentRule;
import com.organize.rules.ComponentRuleContext;
import com.organize.rules.impl.AddComponentRule;
import com.organize.rules.impl.ComponentRuleContextImpl;
import com.organize.serives.ComponentInfoService;
import com.organize.serives.impl.WindowsComponentInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

/**
 * 自动配置
 * <p>
 * </p>
 *
 * @description TODO
 * @author: 老码农
 * @create: 2020-10-15 16:27
 **/
@Configuration
@EnableConfigurationProperties({OrganizeComponentProperties.class})
public class OrganizeAutoConfiguration {

    /**
     * 日志
     */
    private static final Logger logger = LoggerFactory.getLogger(OrganizeAutoConfiguration.class);

    public OrganizeAutoConfiguration() {

    }

    /**
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(ComponentInfo.class)
    public ComponentInfo componentInfo() {
        logger.info("正在自动配置 ComponentInfo .....................................");
        return new ComponentInfo();
    }

    /**
     * Windows 注入
     *
     * @return
     */
    @Bean
    @Conditional(OsWindowsCondition.class)
    @ConditionalOnMissingBean(ComponentInfoService.class)
    public ComponentInfoService windowComponentInfoService() {
        return new WindowsComponentInfoService();
    }

    /**
     * 非 Windows 注入
     *
     * @return
     */
    @Bean
    @Conditional(OsNotWindowsCondition.class)
    @ConditionalOnMissingBean(ComponentInfoService.class)
    public ComponentInfoService notWindowsComponentInfoService() {
        return new WindowsComponentInfoService();
    }

    /**
     * 规则上下文
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(ComponentRuleContext.class)
    public ComponentRuleContext componentRuleContext() {
        return new ComponentRuleContextImpl();
    }

    /**
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(AddComponentRule.class)
    public AddComponentRule addComponentRule() {
        return new AddComponentRule();
    }

    /**
     * 默认字典回调
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(DictionaryTypeCallback.class)
    public DictionaryTypeCallback dictionaryTypeCallback() {
        return new DefaultDictionaryTypeCallback();
    }

    /**
     * 部门服务
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(DepartmentAppService.class)
    public DepartmentAppService departmentAppService() {
        return new DepartmentAppServiceImpl();
    }

    /**
     * 职员服务
     *
     * @param dictionaryTypeCallback
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(EmployeeAppService.class)
    public EmployeeAppService employeeAppService(DictionaryTypeCallback dictionaryTypeCallback) {
        return new EmployeeAppServiceImpl(dictionaryTypeCallback);
    }


    /**
     * 模块菜单插件
     *
     * @param properties
     * @return
     */
    @Bean
    @Order(TableAutoDefinitionListener.BEAN_BEGIN_ORDER + 1000)
    @Conditional(OrganizeComponentMenuPluginCondition.class)
    @ConditionalOnMissingBean(OrganizeResourcesModulePluginImpl.class)
    @ConditionalOnBean(AuthorizationResourcesDataSourceListener.class)
    public ResourcesModulePlugin organizeResourcesModulePlugin(OrganizeComponentProperties properties) {
        return new OrganizeResourcesModulePluginImpl(properties);
    }

    /**
     * 拦截
     *
     * @param context
     * @return
     */
    @Bean
    public BeanPostProcessor organizeComponentBeanPostProcessor(final ComponentRuleContext context) {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof ComponentRule) {
                    ComponentRule rule = (ComponentRule) bean;
                    context.registerRule(rule);
                }
                return bean;
            }

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                return bean;
            }
        };
    }

}
